#include "Channel.h"
#include "EventLoop.h"
#include "Logger.h"

#include <sys/epoll.h>

const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI;
const int Channel::kWriteEvent = EPOLLOUT;

Channel::Channel(EventLoop* loop, int fd)
  : m_loop(loop)
  , m_fd(fd)
  , m_events(0)
  , m_revents(0)
  , m_index(-1)
  , m_tied(false)
{}

Channel::~Channel()
{
}

void Channel::tie(const std::shared_ptr<void>& obj)
{
  m_tie = obj;
  m_tied = true;
}

// 负责调用 epoll_ctl
void Channel::update()
{
  // 通过 channel 所属的 eventloop 调用 poller的相应方法
  m_loop->updateChannel(this);
}

// 通过 channel 所属的 EventLoop 调用 poller 相应的方法
void Channel::remove()
{
  m_loop->removeChannel(this);
}

void Channel::handleEvent(Timestamp receiveTime)
{
  if (m_tied) {
    std::shared_ptr<void> guard = m_tie.lock();
    if (guard) {
      handleEventWithGuard(receiveTime);
    }
  } else {
    handleEventWithGuard(receiveTime);
  }
}

void Channel::handleEventWithGuard(Timestamp receiveTime)
{
  //LOG_INFO("channel handleEvent revents:%d\n", m_revents)
  if ((m_revents & EPOLLHUP) && !(m_revents & EPOLLIN)) {
    if (m_closeCallback) {
      m_closeCallback();
    }
  }

  if (m_revents & EPOLLERR) {
    if (m_errorCallback) {
      m_errorCallback();
    }
  }

  if (m_events & (EPOLLIN | EPOLLPRI)) {
    if (m_readCallback) {
      m_readCallback(receiveTime);
    }
  }

  if (m_events & EPOLLOUT) {
    if (m_writeCallback) {
      m_writeCallback();
    }
  }
}